【AWS】RDS for PostgreSQLで文字コード、タイムゾーンを指定してデータインポートしてみた
はじめに
こんにちは植木和樹です。昨年のre:InventにてRDSのPostgreSQL対応が発表されました。
- Amazon Web Services ブログ: 【AWS発表】Amazon RDS for PostgreSQLがご利用可能になりました!
- Amazon RDS for PostgreSQLがやってきた!! | Developers.IO
最近オンプレミスで稼働しているPostgreSQL DBのデータをインポートする機会がありましたので、本日はその備忘録となります。
環境
- エクスポート元のバージョン
- 7.4.8
- インポート先のバージョン
- 9.3.1
- インポート先DBの管理者ユーザー
- awsuser
- インポート先DBのエンドポイント
- postgres.ap-northeast-1.rds.amazonaws.com
インポート前の事前作業
既存のデータをインポートするということで以下のような作業を行いました。
- タイムゾーンをJST(+0900)に変更
- 文字コードをEUC-JPに変更
タイムゾーンをJST(+0900)に変更
デフォルトのパラメーターで時刻を取得するとUTCで返ってきます。DBに接続してcurrent_timestampを実行して確認してみましょう。
$ psql -U awsuser -h postgres.ap-northeast-1.rds.amazonaws.com -d template1 template1=> select current_timestamp; now ------------------------------- 2014-01-31 04:26:11.506471+00 (1 行)
+00とUTCで結果が返ってきています。そこでパラメーターグループでタイムゾーンをJST変更します。なおパラメーターグループはdefault.postgres9.3をベースにインスタンス独自のパラメーターグループを作成済みです。
"timezone" = "JST-9"
パラメーターグループはリブートなしで反映され"in-sync"になりますが、実際にDBに反映されるためにはリブートが必要になります。リブートしたら再度DBに接続してcurrent_timestampを実行してみます。
$ psql -U awsuser -h postgres.ap-northeast-1.rds.amazonaws.com -d template1 template1=> select current_timestamp; now ------------------------------- 2014-01-31 14:33:18.275635+09 (1 行)
ちゃんとJSTで時刻が返ってきています!
PostgreSQLのタイムゾーン設定についてはPostgreSQL 9.3.2文書の「クライアント接続デフォルト」「日付/時刻データ型」を参考にしました。
文字コードをEUC-JPに変更
パラメーターグループで下記4つのパラメーターを変更します。
"lc_messages" = "ja_JP.eucJP" "lc_monetary" = "ja_JP.eucJP" "lc_numeric" = "ja_JP.eucJP" "lc_time" = "ja_JP.eucJP"
設定によってどのようにPostgreSQLの挙動が変わるのかは「ロケール(国際化と地域化) — Let's Postgres」が詳しいです。
インポート作業
pg_dumpコマンドで取得したダンプファイルをインポートします。インポート前にcreateuserコマンドを使って必要なユーザー(user1)を作っておきましょう。
$ createuser -U awsuser -h postgres.ap-northeast-1.rds.amazonaws.com -P user1 (user1のパスワードを入力する) (管理者ユーザー awsuser のパスワードを入力する)
次にインポート先のDB(mydb)を作成します。
2014/02/19 追記
lc_collate や lc_ctype がUTF-8のままだとorder by句やlower関数の結果が意図しないものになります。この2つはcreate database時のみ指定可能なため記述を追加しました。
$ psql -U awsuser -h postgres.ap-northeast-1.rds.amazonaws.com -d template1 template1=> create database mydb LC_COLLATE 'ja_JP.eucJP' LC_CTYPE 'ja_JP.eucJP' ENCODING 'EUC_JP' TEMPLATE template0; CREATE DATABASE template1=> \l データベース一覧 名前 | 所有者 | エンコーディング | 照合順序 | Ctype(変換演算子) | アクセス権 -----------+----------+------------------+-------------+-------------------+----------------------- postgres | awsuser | UTF8 | en_US.UTF-8 | en_US.UTF-8 | rdsadmin | rdsadmin | UTF8 | en_US.UTF-8 | en_US.UTF-8 | rdsadmin=CTc/rdsadmin mydb | awsuser | EUC_JP | ja_JP.eucJP | ja_JP.eucJP | template0 | rdsadmin | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/rdsadmin + | | | | | rdsadmin=CTc/rdsadmin template1 | awsuser | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/awsuser + | | | | | awsuser=CTc/awsuser
psqlコマンドでダンプファイル(pg_dump.sql)をインポートします。インポートログ(pg_import.log)も出力しておきましょう。
$ psql -U awsuser -h postgres.ap-northeast-1.rds.amazonaws.com -d mydb \ -f pg_dump.sql --log-file pg_import.log
インポートが完了したら\dコマンドでテーブル、ビュー、シーケンスの一覧を表示しオブジェクトが作成されていることを確認しましょう。
$ psql -U user1 -h postgres.ap-northeast-1.rds.amazonaws.com -d mydb mydb=> \d リレーションの一覧 スキーマ | 名前 | 型 | 所有者 ----------+-----------------------------+------------+-------- public | my_tbl | テーブル | user1 public | my_seq | シーケンス | user1
問題なくインポートできていますね!
まとめ
PostgreSQLにさわるのは15年ぶりくらいなので、久々だと色々忘れていて時間がかかってしまいました。
なおm1.smallだと15MBほどのファイルのインポートに14分ほどかかりました。なんだかinsertのたびにcommitが走っているような気がします。autocommitでも有効になっているのでしょうか?もうちょっとインポートが早くなる方法を引き続き探してみたいと思います。